package com.oig.sys.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.oig.common.constants.CommonEnum;
import com.oig.common.exception.BadRequestException;
import com.oig.common.module.SysPageInfo;
import com.oig.common.module.SysRequest;
import com.oig.sys.base.dao.ITbBankNoDao;
import com.oig.sys.base.dto.BankNoDto;
import com.oig.sys.base.entity.TbBankNo;
import com.oig.sys.base.service.ITbBankNoService;
import com.oig.sys.base.vo.BankNoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wuxl
 */
@Slf4j
@Service
public class TbBankNoServiceImpl implements ITbBankNoService {

	private final ITbBankNoDao tbBankNoDao;

	@Autowired
	public TbBankNoServiceImpl( ITbBankNoDao tbBankNoDao){
		 this.tbBankNoDao = tbBankNoDao;
	}

	@Transactional
	@Override
	public BankNoVo addOrUpdateBankNo(BankNoDto bankNoDto) {
		TbBankNo bankNo = new TbBankNo();
		BeanUtils.copyProperties(bankNoDto, bankNo);
		if("X".equals(bankNoDto.getDelete())){
			bankNo.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		}else{
			if (StringUtils.isBlank(bankNo.getStatus())){
				bankNo.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
			}
		}
		this.tbBankNoDao.save(bankNo);
		BankNoVo bankNoVo = new BankNoVo();
		BeanUtils.copyProperties(bankNo, bankNoVo);
		return bankNoVo;
	}

	@Transactional
	@Override
	public void cancelTbBankNoList(List<String> bankNoList) {
		List<TbBankNo> delList = this.tbBankNoDao.findByBankNoList(bankNoList);
		if (delList!=null&&!delList.isEmpty()){
			delList.forEach(item->{
				item.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
				this.tbBankNoDao.save(item);//非批量操作
			});
		}
	}

	@Transactional
	@Override
	public BankNoVo addTbBankNo(BankNoDto bankNoDto) {
		TbBankNo bankNo = this.tbBankNoDao.getByBankNo(bankNoDto.getBankNo()) ;
		if (bankNo!=null){
			throw new BadRequestException("行号重复") ;
		}
		bankNo = new TbBankNo();
		BeanUtils.copyProperties(bankNoDto, bankNo);
		bankNo.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbBankNoDao.save(bankNo);
		BankNoVo bankNoVo = new BankNoVo();
		BeanUtils.copyProperties(bankNo, bankNoVo);
		return bankNoVo;
	}

	@Transactional
	@Override
	public BankNoVo updateTbBankNo(BankNoDto bankNoDto) {
		TbBankNo bankNo = this.tbBankNoDao.getByBankNo(bankNoDto.getBankNo()) ;
		if (bankNo==null){
			throw new BadRequestException("记录不存在") ;
		}
		//bankNo 数据库建唯一约束
		BeanUtils.copyProperties(bankNoDto, bankNo, "status");
		this.tbBankNoDao.save(bankNo);
		BankNoVo bankNoVo = new BankNoVo();
		BeanUtils.copyProperties(bankNo, bankNoVo);
		return bankNoVo;
	}

	@Transactional
	@Override
	public void cancelTbBankNo(String bankNo) {
		TbBankNo bank = this.tbBankNoDao.getByBankNo(bankNo) ;
		if (bank==null){
			throw new BadRequestException("记录不存在") ;
		}
		bank.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		this.tbBankNoDao.save(bank);
	}

	@Override
	public SysPageInfo<BankNoVo> findTbBankNo(SysRequest<BankNoDto> bankNoRequest) {
		Pageable pageable = bankNoRequest.pageable();
		Page<TbBankNo> page ;
		if (bankNoRequest.getParamDto()!=null){
			Specification<TbBankNo> specification = new Specification<TbBankNo>() {
				@Override
				@Nullable
				public Predicate toPredicate(@NonNull Root<TbBankNo> root, @NonNull CriteriaQuery<?> criteriaQuery, @NonNull CriteriaBuilder criteriaBuilder) {
					List<Predicate> predicateList = new ArrayList<>();
					if (StrUtil.isNotBlank(bankNoRequest.getParamDto().getBankName())) {
						Path<String> bankNoNamePath = root.get("bankName");
						predicateList.add(criteriaBuilder.like(bankNoNamePath, "%" + bankNoRequest.getParamDto().getBankName() + "%"));
					}
					if (StrUtil.isNotBlank(bankNoRequest.getParamDto().getBankNo())) {
						Path<String> bankNoPath = root.get("bankNo");
						predicateList.add(criteriaBuilder.like(bankNoPath, "%" + bankNoRequest.getParamDto().getBankNo()+ "%"));
					}
					Path<String> statusPath = root.get("status");
					if (StrUtil.isNotBlank(bankNoRequest.getParamDto().getStatus())) {
						log.debug("query status");
						predicateList.add(criteriaBuilder.equal(statusPath, bankNoRequest.getParamDto().getStatus()));
					} else {
						predicateList.add(criteriaBuilder.equal(statusPath, CommonEnum.CommonStatusEnum.OK.getCode()));
					}
					criteriaQuery.where(predicateList.toArray(new Predicate[0]));
					return criteriaQuery.getRestriction();
				}
			};
			page = this.tbBankNoDao.findAll(specification,pageable);
		} else {
			page = this.tbBankNoDao.findAll(pageable);
		}
		List<BankNoVo> bankNoVoList = new ArrayList<>();
		for (TbBankNo bankNo : page.getContent()){
			BankNoVo bankNoVo = new BankNoVo();
			BeanUtils.copyProperties(bankNo, bankNoVo);
			bankNoVoList.add(bankNoVo);
		}
		SysPageInfo<BankNoVo> sysPageInfo = new SysPageInfo<>(bankNoRequest.getPageNo(), bankNoRequest.getPageSize(), page.getTotalElements());
		sysPageInfo.setList(bankNoVoList);
		return sysPageInfo;
	}
	@Override
	public List<BankNoVo> getByBankNo(List<String> bankNoList) {
		List<TbBankNo> byBankNoList = this.tbBankNoDao.findByBankNoList(bankNoList);
		return BeanUtil.copyToList(byBankNoList,BankNoVo.class);
	}
}
